#include "login_module.h"

#include <boost/asio.hpp>
using namespace boost;
using namespace boost::asio;

#include <common/log/log.h>
#include <common/net/message_parse.h>
#include <common/net/session.h>

#include <protocols/protos/common.pb.h>
using namespace proto::common;
#include <protocols/protos/db.pb.h>
#include <protocols/protos/login.pb.h>
using namespace proto::login;
#include <protocols/protos/tables.pb.h>
using namespace proto::tables;

#include <common/utils/util.h>

#include "base/sub_server_mgr.h"

bool LoginModule::doDispatch(const std::shared_ptr<SubServerMgr>& submgr,
                         const std::shared_ptr<Player>& player,
                         const MessageID& msgID,
                         const char* buf,
                         std::size_t bufSize)
{
    LOG_WARN("doDispatch not implement.");
    return false;
}

bool LoginModule::doDispatch(const std::shared_ptr<Session>& session,
                             const MessageID& msgID,
                             const char* buf,
                             std::size_t bufSize)
{
    switch (msgID.stMsg.msgID)
    {
    case S2C_LOGIN_RET:
        return onLoginRet(session, msgID, buf, bufSize);

    case S2C_CREATE_PLAYER_RET:
        return onCreatePlayerRet(session, msgID, buf, bufSize);

    case S2C_CHOOSE_PLAYER_RET:
        return onChoosePlayerRet(session, msgID, buf, bufSize);

    case S2C_LOGIN_CONFIRM_RET:
        return onLoginConfirmRet(session, msgID, buf, bufSize);

    default:
        return false;
    }

    return false;
}

bool LoginModule::onLoginRet(const std::shared_ptr<Session>& session,
                             const MessageID& msgID,
                             const char* buf,
                             std::size_t bufSize)
{
    LoginRet ret;
    if (!ret.ParseFromArray(buf, bufSize))
    {
        LOG_ERROR("Parse proto data failed.");
        return false;
    }
    LOG_DEBUG("Got login ret msg");

    if (ret.err() == eCREATE_NEW_PLAYER)
    { // 请求创建角色
        CreatePlayerReq req;
        req.set_player_name(ret.rand_name());
        req.set_acc_id(ret.acc_id());
        req.set_head_id(1);
        LOG_DEBUG("request create player:" << ret.rand_name());
        return session->sendMsg(proto::common::eLogin, C2S_CREATE_PLAYER_REQ, req);
    }
    else if (ret.err() == eALREADY_LOGIN)
    {
        LOG_DEBUG("account already login." << ret.acc_id());
        LoginConfirmReq req;
        req.set_acc_id(ret.acc_id());
        return session->sendMsg(proto::common::eLogin, C2S_LOGIN_CONFIRM_REQ, req);
    }
    else if (ret.err() == eSUC)
    {
        if (ret.players_size() <= 0)
        {
            LOG_ERROR("No player returned.");
            return false;
        }
        uint32_t playerID = ret.players(0).player_id();
        LOG_DEBUG("Choose playerID is :" << playerID << " accID: " << ret.acc_id());

        ChoosePlayerReq req;
        req.set_acc_id(ret.acc_id());
        req.set_player_id(playerID);
        return session->sendMsg(proto::common::ModuleType::eLogin, C2S_CHOOSE_PLAYER_REQ, req);
    }

    return false;
}

bool LoginModule::onCreatePlayerRet(const std::shared_ptr<Session>& session,
                                    const MessageID& msgID,
                                    const char* buf,
                                    std::size_t bufSize)
{
    CreatePlayerRet ret;
    if (!ret.ParseFromArray(buf, bufSize))
    {
        LOG_ERROR("Parse proto data failed.");
        return false;
    }

    LOG_DEBUG("Got create player ret msg");

    if (ret.err() != eSUC)
    {
        LOG_ERROR("Create player failed. error code:" << ret.err());
        return false;
    }

    ChoosePlayerReq req;
    req.set_acc_id(ret.acc_id());
    req.set_player_id(ret.player_id());
    return session->sendMsg(proto::common::ModuleType::eLogin, C2S_CHOOSE_PLAYER_REQ, req);
}

bool LoginModule::onChoosePlayerRet(const std::shared_ptr<Session>& session,
                                    const MessageID& msgID,
                                    const char* buf,
                                    std::size_t bufSize)
{
    ChoosePlayerRet ret;
    if (!ret.ParseFromArray(buf, bufSize))
    {
        LOG_ERROR("Parse proto data failed.");
        return false;
    }
    LOG_DEBUG("Got choose player ret msg");
    LOG_DEBUG("choose player: " << ret.err());
    return true;
}

bool LoginModule::onLoginConfirmRet(const std::shared_ptr<Session>& session,
                                    const MessageID& msgID,
                                    const char* buf,
                                    std::size_t bufSize)
{

    LOG_DEBUG("Got confirm ret msg");
    return true;
}
